package com.smh.demo1.a13;

import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;

/**
 * @author shiminghui
 * @date 2025/4/16 20:30
 * @description: TODO
 */
public class A13Application {
    public static void main(String[] args) throws NoSuchMethodException {

        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        //匹配方法
//        pointcut.setExpression("execution(* com.smh.demo1.a13.A13Application.Target.read(..))");
//        System.out.println(pointcut.matches(Target.class.getMethod("read", int.class), Target.class));
//        System.out.println(pointcut.matches(Target.class.getMethod("test"), Target.class));

        // 匹配注解
        pointcut.setExpression("@annotation(org.springframework.transaction.annotation.Transactional)");
        System.out.println(pointcut.matches(Target.class.getMethod("read", int.class), Target.class));
        System.out.println(pointcut.matches(Target.class.getMethod("test"), Target.class));

        System.out.println(pointcut.matches(Target2.class.getMethod("read", int.class), Target2.class));
        System.out.println(pointcut.matches(Target2.class.getMethod("test"), Target2.class));

        System.out.println(pointcut.matches(Target3.class.getMethod("read", int.class), Target3.class));
        System.out.println(pointcut.matches(Target3.class.getMethod("test"), Target3.class));


        StaticMethodMatcherPointcut pointcut2 = new StaticMethodMatcherPointcut() {
            @Override
            public boolean matches(Method method, Class<?> targetClass) {

                /*MergedAnnotations from = MergedAnnotations.from(method);
                if (from.get(Transactional.class).isPresent()){
                    return true;
                }*/

                // 检查类上面是否有注解
                Transactional annotation = targetClass.getAnnotation(Transactional.class);
                if (annotation != null) {
                    return true;
                }

                /*MergedAnnotations from = MergedAnnotations.from(targetClass, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY);
                if (from.get(Transactional.class).isPresent()){
                    return true;
                }*/

                // 检查接口上面是否有注解
                for (Class<?> anInterface : targetClass.getInterfaces()) {
                    if (anInterface.getAnnotation(Transactional.class) != null) {
                        return true;
                    }
                }

                // 检查方法上面是否有注解
                Transactional annotation1 = method.getAnnotation(Transactional.class);
                if (annotation1 != null) {
                    return true;
                }
                return false;
            }
        };
        System.out.println("----------------------------------------");
        System.out.println(pointcut2.matches(Target2.class.getMethod("read", int.class), Target2.class));
        System.out.println(pointcut2.matches(Target2.class.getMethod("test"), Target2.class));

        System.out.println(pointcut2.matches(Target3.class.getMethod("read", int.class), Target3.class));
        System.out.println(pointcut2.matches(Target3.class.getMethod("test"), Target3.class));

    }


    @Transactional
    interface Inter {
        public void read(int sum);

        public void test();
    }

    static class Target {
        public void read(int sum) {
            System.out.println("Target.read");
        }

        @Transactional
        public void test() {
            System.out.println("Target.test");
        }
    }

    @Transactional
    static class Target2 {
        public void read(int sum) {
            System.out.println("Target2.read");
        }

        public void test() {
            System.out.println("Target2.test");
        }
    }

    static class Target3 implements Inter {

        @Override
        public void read(int sum) {
            System.out.println("Target3.read");
        }

        @Override
        public void test() {
            System.out.println("Target3.test");
        }
    }


}
